<template>
  <h1>监听数据源类型</h1>
  <input type="text" v-model="inpuVal" />
  <div>
    <label for="">num1:</label>
    <input type="number" v-model="num" />
    <br />
    <label for="">num2:</label>
    <input type="number" v-model="num2" />
    <h4>求和为：{{ sumcouputed }}</h4>
  </div>

  <div>
    <h1>侦听器 watchEffect</h1>
    <p>
      watch 的第一个参数可以是不同形式的“数据源”：它可以是一个 ref
      (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组：
    </p>
    <div>inputVal: <input type="text" v-model="inpuVal" /></div>

    <hr />
    <div>
      <input type="text" v-model="ruser.name" />
      <input type="text" v-model="ruser.sex" />
      <input type="text" v-model="ruser.love.lanqiu" />
    </div>

    <hr />
    <div
      ref="my-input"
      style="width: 100px; height: 100px; background-color: aqua"
      v-if="isShow"
    ></div>
    <button type="button" @click="changeShow">显示正方形</button>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref, useTemplateRef, watch, watchEffect } from 'vue'

const inpuVal = ref('')
const num = ref(0)
const num2 = ref(0)
const sumcouputed = computed(() => {
  return num.value + num2.value
})
watch(inpuVal, (newVal, oldVal) => {
  console.log(newVal)
  console.log(oldVal)
})
watch(sumcouputed, (newVal, oldVal) => {
  console.log(newVal)
  console.log(oldVal)
})
watchEffect(() => {
  console.log(sumcouputed.value, 'watchEffect:sumcouputed')
})
// getter函数
watch(
  () => inpuVal.value,
  (newVal, oldVal) => {
    console.log(newVal, 'getnew')
    console.log(oldVal, 'getold')
  }
)

const ruser = reactive({
  name: '李四',
  sex: '男',
  love: {
    lanqiu: '篮球'
  }
})

const isShow = ref(false)
const inputDom = useTemplateRef('my-input')

const changeShow = () => {
  isShow.value = true
}

// 回调的触发时机
// 默认情况下，侦听器回调会在父组件更新 (如有) 之后、所属组件的 DOM 更新之前被调用。
// 这意味着如果你尝试在侦听器回调中访问所属组件的 DOM，那么 DOM 将处于更新前的状态。
// watchEffect(() => {
//   console.log(isShow.value, 'wacthEffect:inoutVal')
//   console.log(inputDom.value, 'wacthEffect:inputDom')
// })

// watch(isShow, () => {
//   console.log(inputDom.value, 'wacth:inputDom') //null
// })

// 如果想在侦听器回调中能访问被 Vue 更新之后的所属组件的 DOM，你需要指明 flush: 'post' 选项：
watch(
  isShow,
  () => {
    console.log(inputDom.value, 'wacth:post,inputDom')
  },
  {
    flush: 'post'
  }
)

watchEffect(() => {
  console.log((() => inpuVal.value)(), 'watchEffect:(()=>inpuVal,value)()')
})

// watch(
//   [inpuVal, () => num.value * num2.value, () => inpuVal.value, () => num.value + num2.value],
//   ([val1, val2, val3, val4]) => {
//     console.log(val1)
//     console.log(val2)
//     console.log(val3)
//     console.log(val4)
//   }
// )

// 但是对于有多个依赖项的侦听器来说，使用 watchEffect() 可以消除手动维护依赖列表的负担
watchEffect(() => {
  const [cheng, ival, sum] = [
    (() => num.value * num2.value)(),
    (() => inpuVal.value)(),
    (() => num.value + num2.value)()
  ]
  console.log(cheng, ival, sum, 'chen,ival,sum')
})

// 如果你需要侦听一个嵌套数据结构中的几个属性，watchEffect() 可能会比深度侦听器更有效，
// 因为它将只跟踪回调中被使用到的属性，而不是递归地跟踪所有的属性。
watchEffect(() => {
  console.log(ruser.love.lanqiu, 'watchEffect:ruser.love.lanqiu')
})

watchEffect(() => {
  console.log(ruser.name)
  console.log(ruser.love.lanqiu, '2watchEffect:ruser.love.lanqiu')
})

// 这种方式直接使用ref，值在变化的时候侦听不到
watchEffect(() => {
  console.log(inpuVal, '不是value')
})
</script>

<style></style>
